//
//  NSArray+KLException.m
//  KoalaUtilKit
//
//  Created by Tommy on 15/1/29.
//  Copyright (c) 2015年 Koala Team. All rights reserved.
//

#import "NSArray+KLException.h"
#import "KLLog.h"
#import "NSObject+KLSwizzle.h"




@implementation NSArray (KLException)

#if KLENABLE_EXCEPTION_SWIZZLE

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class cls = [[self array] class];
        [cls kl_swizzleInstanceSelector:@selector(objectAtIndex:) withNewSelector:KLHookedSel(objectAtIndex:)];
        [self kl_swizzleClassSelector:@selector(arrayWithObjects:count:) withNewSelector:KLHookedSel(arrayWithObjects:count:)];
    });
}



- (id)KLHookedMethod(objectAtIndex:(NSUInteger)index){
    __autoreleasing id instance = nil;
    if([self checkRange:index]){
        @try{
            instance = [self KLHookedMethod(objectAtIndex:)index];
         }
        @catch (NSException *exception) {
            NSAssert(0,@"exception:%@",exception);
            KLLogError(@"exception:%@",exception);
        }
    }else{
       NSAssert(0,@"catch out of range:%lul in %@ ",(unsigned long)index,self);
       KLLogError(@"catch out of range:%lul in %@ ",(unsigned long)index,self);
    }

    return instance;
}

- (BOOL)checkRange:(NSUInteger)index{
    return [self count] > index;
}

+ (void) _kl_removeObjectFromArray:(const id [])objects at:(NSUInteger) index count:(NSUInteger)cnt{
    __unsafe_unretained id* objs = (__unsafe_unretained id*) objects;
    for(NSUInteger i=index;i<cnt&&(i+1)<cnt;++i){
        objs[i] = objs[i+1];
    }
}
+ (instancetype)KLHookedMethod(arrayWithObjects:(const id [])objects count:(NSUInteger)cnt){
    NSUInteger count = cnt;
    for(NSUInteger i = 0; i < count; ++i){
        if(!objects[i]) {
            NSAssert(0,@"insert nil at %d",i);
            KLLogError(@"insert nil at %d",i);
            [self _kl_removeObjectFromArray:objects at:i count:count--];
        }
    }
    
    return [self KLHookedMethod(arrayWithObjects:objects count:count)];
}

#endif //KLENABLE_EXCEPTION_SWIZZLE

@end
